package com.smartstate.EnvironmentMonitor.util;

import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;

import com.smartstate.EnvironmentMonitor.constant.QueryWapperEnum;
import com.smartstate.EnvironmentMonitor.util.querywapper.QueryWapper;
import com.smartstate.EnvironmentMonitor.util.querywapper.UpdateWapper;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.Field;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description 拼接查询条件工具类
 */
public class WrapperUtil {

    public static final char UNDERLINE = '_';

    /**
     * 拼接查询条件
     *
     * @param obj          数据实体
     * @return void 返回参数说明
     * @exception/throws
     */
    public static <T> QueryWrapper<T> convertQuery(Object obj, Class<T> tClass) {
        //创建查询语句包装器和分页查询表对象
        QueryWrapper<T> wrapper =new QueryWrapper();
        if(!ObjectUtils.isEmpty(obj)) {
            Class clazz = obj.getClass();
            while (!clazz.getName().equals("java.lang.Object")) {
                foreachQueryClass(wrapper, obj, clazz);
                clazz = clazz.getSuperclass();
            }
        }
        return wrapper;
    }

    /**
     * 拼接查询条件
     *
     * @param queryWrapper 条件对象
     * @param obj          数据实体
     * @return void 返回参数说明
     * @exception/throws
     */
    public static void convertQuery(QueryWrapper queryWrapper, Object obj) {
        if(!ObjectUtils.isEmpty(obj)) {
            Class clazz = obj.getClass();
            while (!clazz.getName().equals("java.lang.Object")) {
                foreachQueryClass(queryWrapper, obj, clazz);
                clazz = clazz.getSuperclass();
            }
        }
    }

    /***
     * 拼接查询语句
     * @param queryWrapper 条件对象
     * @param obj 数据实体
     * @param clazz 数据类
     */
    private static void foreachQueryClass(QueryWrapper queryWrapper, Object obj, Class clazz){
        try {
            for (Field field : clazz.getDeclaredFields()) {
                // 抑制Java对修饰符的检查
                field.setAccessible(true);

                // 获取属性值
                Object fieldValue =  field.get(obj);

                queryWrapperPackaging(field,queryWrapper,fieldValue);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 拼接修改语句
     *
     * @param obj          数据实体
     * @return void 返回参数说明
     * @exception/throws
     */
    public static <T> UpdateWrapper<T> convertUpdate(Object obj,Class<T> tClass) {
        UpdateWrapper<T> wrapper = new UpdateWrapper();
        if(!ObjectUtils.isEmpty(obj)) {
            Class clazz = obj.getClass();
            while (!clazz.getName().equals("java.lang.Object")) {
                foreachUpdateClass(wrapper, obj, clazz);
                clazz = clazz.getSuperclass();
            }
        }
        return wrapper;
    }

    /**
     * 拼接修改语句
     *
     * @param updateWrapper 条件对象
     * @param obj          数据实体
     * @return void 返回参数说明
     * @exception/throws
     */
    public static void convertUpdate(UpdateWrapper updateWrapper, Object obj) {
        if(!ObjectUtils.isEmpty(obj)) {
            Class clazz = obj.getClass();
            while (!clazz.getName().equals("java.lang.Object")) {
                foreachUpdateClass(updateWrapper, obj, clazz);
                clazz = clazz.getSuperclass();
            }
        }
    }

    /**
     * 封装对象修改语句
     * @param updateWrapper 条件对象
     * @param obj 数据实体
     * @param clazz 数据类
     */
    private static void foreachUpdateClass(UpdateWrapper updateWrapper, Object obj, Class clazz){
        try {
            for (Field field : clazz.getDeclaredFields()) {
                // 抑制Java对修饰符的检查
                field.setAccessible(true);
                // 获取属性值
                Object fieldValue =  field.get(obj);
                //拼接修改查询条件
                queryWrapperPackaging(field,updateWrapper,fieldValue);
                //拼接修改条件
                UpdateWapper updateWapperAnnotation = AnnotationUtils.getAnnotation(field,UpdateWapper.class);
                if(ObjectUtils.isEmpty(updateWapperAnnotation)){
                    continue;
                }
                // 检查数据库映射字段名是否为空，为空将字段名修改为下滑分隔作为字段名
                String fieldName = updateWapperAnnotation.field();
                fieldName = ObjectUtils.isEmpty(fieldName)?camelToUnderline(field.getName()):fieldName;
                updateWrapper.set(!ObjectUtils.isEmpty(fieldValue),fieldName,fieldValue);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 封装查询条件
     * @param field 字段
     * @param wrapper 条件对象
     */
    public static void queryWrapperPackaging(Field field, AbstractWrapper wrapper, Object fieldValue){
        // 查询注解
        QueryWapper queryWapperAnnotation = AnnotationUtils.getAnnotation(field, QueryWapper.class);
        if(ObjectUtils.isEmpty(queryWapperAnnotation)){
            return;
        }
        // 检查数据库映射字段名是否为空，为空将字段名修改为下滑分隔作为字段名
        String fieldName = queryWapperAnnotation.field();
        fieldName = ObjectUtils.isEmpty(fieldName)?camelToUnderline(field.getName()):fieldName;
        // 获取枚举
        QueryWapperEnum queryWapperEnum = queryWapperAnnotation.queryWapperEnum();
        // 拼接查询条件
        switch (queryWapperEnum) {
            case EQ:
                wrapper.eq(!ObjectUtils.isEmpty(fieldValue), fieldName, fieldValue);
                break;
            case LIKE:
                wrapper.like(!ObjectUtils.isEmpty(fieldValue), fieldName, fieldValue);
                break;
            case GE:
                wrapper.ge(!ObjectUtils.isEmpty(fieldValue), fieldName, fieldValue);
                break;
            case LE:
                wrapper.le(!ObjectUtils.isEmpty(fieldValue), fieldName, fieldValue);
                break;
            case GT:
                wrapper.gt(!ObjectUtils.isEmpty(fieldValue), fieldName, fieldValue);
                break;
            case LT:
                wrapper.lt(!ObjectUtils.isEmpty(fieldValue), fieldName, fieldValue);
                break;
            case IN:
                wrapper.in(!ObjectUtils.isEmpty(fieldValue), fieldName, (List)fieldValue);
                break;
            default:
                break;
        }
    }

    /**
     * 驼峰格式字符串转换为下划线格式字符串
     *
     * @param param
     * @return
     */
    public static String camelToUnderline(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (Character.isUpperCase(c)) {
                sb.append(UNDERLINE);
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 下划线格式字符串转换为驼峰格式字符串
     *
     * @param param
     * @return
     */
    public static String underlineToCamel(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (c == UNDERLINE) {
                if (++i < len) {
                    sb.append(Character.toUpperCase(param.charAt(i)));
                }
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 下划线格式字符串转换为驼峰格式字符串2
     *
     * @param param
     * @return
     */
    public static String underlineToCamel2(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        StringBuilder sb = new StringBuilder(param);
        Matcher mc = Pattern.compile("_").matcher(param);
        int i = 0;
        while (mc.find()) {
            int position = mc.end() - (i++);
            sb.replace(position - 1, position + 1, sb.substring(position, position + 1).toUpperCase());
        }
        return sb.toString();
    }

}
